package com.kt.mes.opc;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
import org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode;
import org.eclipse.milo.opcua.sdk.core.nodes.Node;
import org.eclipse.milo.opcua.sdk.core.nodes.VariableNode;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.Security;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;

//opc客户端
public class OpcClientUtil {

    static {
        // Required for SecurityPolicy.Aes256_Sha256_RsaPss
        Security.addProvider(new BouncyCastleProvider());
    }

    private final CompletableFuture<OpcUaClient> future = new CompletableFuture<>();

    //创建 OpcClient
    public static OpcUaClient createClient(String url, String name, String pwd,String gw) throws Exception {

        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("unable to create security dir: " + securityTempDir);
        }

        KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);


        return OpcUaClient.create(url, endpoints ->
                endpoints.stream()
                        // .filter( e -> true)
                        .findFirst(), configBuilder ->
                configBuilder
                        .setApplicationName(LocalizedText.english(gw))
                        .setApplicationUri("urn:eclipse:milo:examples:client")
                        .setCertificate(loader.getClientCertificate())
                        .setKeyPair(loader.getClientKeyPair())
                        //.setIdentityProvider(new AnonymousProvider())//无用户名 密码
                        .setIdentityProvider(new UsernameProvider(name, pwd))//
                        .setRequestTimeout(uint(5000))
                        .build());
    }
    //订阅


    public static void main(String[] args) {

        // future
        try {
            OpcUaClient opc = OpcClientUtil.createClient("opc.tcp://192.168.0.60:4840", "admin", "123456","");
            opc.connect().get();
            NodeId nodeId = NodeId.parse("ns=4;i=112");
            UaVariableNode naNode = opc.getAddressSpace().getVariableNode(nodeId);
            System.out.println(naNode.getValue());
            //ns=4;i=108

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //写值
    public static void write(NodeId node, Object ivalue, OpcUaClient client) {


        // 创建连接
        try {
            client.connect().get();
            Variant value = new Variant(ivalue);

            DataValue dataValue = new DataValue(value, null, null);



            StatusCode statusCode = client.writeValue(node, dataValue).get();


            System.out.println("节点【" + node.getIdentifier() + "】写入状态：" + statusCode.isGood());


        } catch (Exception e) {

            e.printStackTrace();
        }

    }

//    public static void write(NodeId node, int ivalue, OpcUaClient client) {
//
//
//        // 创建连接
//        try {
//            client.connect().get();
//            Variant value = new Variant(ivalue);
//
//            DataValue dataValue = new DataValue(value, null, null);
//
//            StatusCode statusCode = client.writeValue(node, dataValue).get();
//            System.out.println("节点【" + node.getIdentifier() + "】写入状态：" + statusCode.isGood());
//
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//    }

    public static String read(NodeId node, OpcUaClient client)
    {
        // 创建连接

        try {
            client.connect().get();
            if (client == null) {
                return "找不到客户端，操作失败";
            }
            UaVariableNode vNode = client.getAddressSpace().getVariableNode(node);
            DataValue value = vNode.readValue();
            return value.getValue().getValue() + "";
        }catch (Exception e){
            return null;

        }


    }


}
